package com.xiaoyy.sso.core.integration.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoyy.core.common.cache.CacheConst;
import com.xiaoyy.core.common.enums.*;
import com.xiaoyy.core.common.exception.AppException;
import com.xiaoyy.core.common.vo.SessionInfo;
import com.xiaoyy.core.common.vo.TokenVO;
import com.xiaoyy.core.config.annotations.ApiService;
import com.xiaoyy.core.config.annotations.OpApi;
import com.xiaoyy.core.config.util.RedisUtil;
import com.xiaoyy.core.config.util.TokenLoginHelper;
import com.xiaoyy.core.dict.integration.DictIntegration;
import com.xiaoyy.sso.common.enums.LoginTypeEnum;
import com.xiaoyy.sso.common.enums.ObjectTypeEnum;
import com.xiaoyy.sso.common.vo.LoginLogVO;
import com.xiaoyy.sso.common.vo.LoginVO;
import com.xiaoyy.sso.common.vo.UserVO;
import com.xiaoyy.sso.common.vo.WinxinVO;
import com.xiaoyy.sso.core.dao.model.*;
import com.xiaoyy.sso.core.integration.LoginLogIntegration;
import com.xiaoyy.sso.core.integration.RsLoginIntegration;
import com.xiaoyy.sso.core.integration.UserIntegration;
import com.xiaoyy.sso.core.service.*;
import com.xiaoyy.sso.core.util.UserSecureUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@ApiService
public class RsLoginIntegrationImpl implements RsLoginIntegration {
    //手机号码正则
    private static Pattern cellphonePattern = Pattern.compile("^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|70)\\d{8}$");//1开头 第二位是3或4或5或7或8 总11位
    private static Pattern emailPattern = Pattern.compile("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");//复杂匹配

    @Value("${system.config.token.cnt.max}")
    private Integer loginMax;
    @Value("${system.config.token.login.clock}")
    private Long clockTime;
    @Value("${system.config.token.login.check.time}")
    private Long checkTime;
    @Value("${system.config.login.imgCode.max}")
    private Integer loginImgCodeMax;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    SysUserService sysUserService;
    @Autowired
    SysUserBasicService sysUserBasicService;
    @Autowired
    SysUserPrivilegeService sysUserPrivilegeService;
    @Autowired
    SysRouterService sysRouterService;
    @Autowired
    SysFunctionService sysFunctionService;
    @Autowired
    SysRouterFuncService sysRouterFuncService;
    @Autowired
    DictIntegration dictIntegration;
    @Autowired
    TokenLoginHelper tokenLoginHelper;
    @Autowired
    SysUserOtherService sysUserOtherService;
    @Autowired
    LoginLogIntegration loginLogIntegration;
    @Autowired
    UserIntegration userIntegration;

    @Override
    @OpApi(funcCode="LOGIN0001",title = "用户登录",funcType= FuncTypeEnum.other,publicFlag = BoolEnum.TRUE)
    public TokenVO login(LoginVO loginVO) {
        // 判断登录次数
        TokenVO tokenVO ;
        LoginLogVO loginLogVO = Convert.convert(LoginLogVO.class,loginVO);
        loginLogVO.setLoginFlag(BoolEnum.FALSE.getType());
        loginLogVO.setLoginTime(new Date());
        try {
            checkLoginMaxCnt(loginVO);
            QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SysUser::getDel, BoolEnum.FALSE.getType())
                    .eq(SysUser::getUserType, loginVO.getUserType());
            if (LoginTypeEnum.username.getType().equalsIgnoreCase(loginVO.getLoginType())) {
                // 用户名密码登录
                String userName = loginVO.getUserName();
                Matcher m = cellphonePattern.matcher(userName);
                Matcher emailM = emailPattern.matcher(userName);
                if (m.matches()) {
                    // 判断是否手机号码
                    queryWrapper.lambda().eq(SysUser::getCellphone, UserSecureUtil.aesEncrypt(userName));
                } else if (emailM.matches()) {
                    queryWrapper.lambda().eq(SysUser::getEmail, UserSecureUtil.aesEncrypt(userName));
                } else if (IdcardUtil.isValidCard(loginVO.getUserName())) {
                    // 判断是否身份证
                    queryWrapper.lambda().eq(SysUser::getIdcard, UserSecureUtil.aesEncrypt(userName));
                } else {
                    // 按用户名字段处理
                    queryWrapper.lambda().eq(SysUser::getUserName, userName);
                }
            } else if (LoginTypeEnum.cellphone.getType().equalsIgnoreCase(loginVO.getLoginType())) {
                // 手机验证码登录
                queryWrapper.lambda().eq(SysUser::getCellphone, UserSecureUtil.aesEncrypt(loginVO.getCellphone()));
            } else if (LoginTypeEnum.email.getType().equalsIgnoreCase(loginVO.getLoginType())) {
                // 邮箱验证码登录
                queryWrapper.lambda().eq(SysUser::getEmail, UserSecureUtil.aesEncrypt(loginVO.getEmail()));
            } else if (LoginTypeEnum.weixin.getType().equalsIgnoreCase(loginVO.getLoginType())) {
                // 微信登录
                getUserOhter(queryWrapper, loginVO);
            } else if (LoginTypeEnum.alipay.getType().equalsIgnoreCase(loginVO.getLoginType())) {
                // 支付宝登录
                getUserOhter(queryWrapper, loginVO);
            } else if (LoginTypeEnum.dingding.getType().equalsIgnoreCase(loginVO.getLoginType())) {
                //钉钉登录
                getUserOhter(queryWrapper, loginVO);
            }
            checkUserType(queryWrapper, loginVO);

            SysUser sysUser = sysUserService.getOne(queryWrapper);
            checkLogin(sysUser, loginVO);
            loginLogVO.setUserId(sysUser.getUserId());
            loginLogVO.setUserName(sysUser.getUserName());
            SessionInfo sessionInfo = createSessionInfo(sysUser, loginVO);
            tokenVO = tokenLoginHelper.login(sessionInfo);
            loginLogVO.setAccessToken(tokenVO.getAccessToken());
            loginLogVO.setLoginFlag(BoolEnum.TRUE.getType());
            loginLogVO.setOnlineFlag(BoolEnum.TRUE.getType());
        }catch (AppException e){
            loginLogVO.setLoginFlag(BoolEnum.FALSE.getType());
            loginLogVO.setFailReason(e.getMsg());
            loginLogVO.setOnlineFlag(BoolEnum.FALSE.getType());
            throw  e;
        }catch (Exception e){
            String msg =  e.getMessage();
            if (StringUtils.isBlank(msg)&&e.getCause()!=null){
                msg=e.getCause().getMessage();
            }
            loginLogVO.setLoginFlag(BoolEnum.FALSE.getType());
            loginLogVO.setFailReason(msg);
            loginLogVO.setOnlineFlag(BoolEnum.FALSE.getType());
            throw  e;
        }finally {
            loginLogIntegration.saveLogin(loginLogVO);
        }
        return tokenVO;
    }

    @Override
    public TokenVO register(LoginVO loginVO) {
        // 校验手机验证码
        this.checkShortCode(loginVO.getCellphone(),loginVO.getShortMsgCode());
        UserVO userVO = Convert.convert(UserVO.class,loginVO);
        userIntegration.addUser(userVO);
        SysUser sysUser=Convert.convert(SysUser.class,userVO);

        return getTokenVO(loginVO,sysUser);
    }


    @Override
    @OpApi(funcCode="LOGIN0002",title = "微信绑定用户",funcType= FuncTypeEnum.other,publicFlag = BoolEnum.TRUE)
    public TokenVO bindWinxinUser(LoginVO loginVO, WinxinVO winxinVO) {
        if (StringUtils.isBlank(loginVO.getLoginType())){
            loginVO.setLoginType(LoginTypeEnum.weixin.getType());
        }
        if (StringUtils.isBlank(loginVO.getCellphone())) {
            throw new AppException("请输入手机号码");
        }
        Matcher m = cellphonePattern.matcher(loginVO.getCellphone());
        if (!m.matches()){
            throw new AppException("请输入正确的手机号码");
        }
        this.checkShortCode(loginVO.getCellphone(),loginVO.getShortMsgCode());

        List<SysUserOther> list = getOtherList(loginVO.getOpenId(),loginVO.getLoginType());
        if (!CollectionUtils.isEmpty(list)) {
            QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SysUser::getDel, BoolEnum.FALSE.getType())
                    .eq(SysUser::getUserType, loginVO.getUserType());
            List<String> userIdList = list.stream().map(SysUserOther::getUserId).collect(Collectors.toList());
            queryWrapper.lambda().in(SysUser::getUserId, userIdList);
            checkUserType(queryWrapper, loginVO);
            List<SysUser> userList = sysUserService.list(queryWrapper);
            if (!CollectionUtils.isEmpty(userList)) {
                throw new AppException(ErrorEnum.SYSTEM_ERROR_ALREAD_BIND);
            }
        }
        // 判断该身份证账号是否存在
        SysUserOther sysUserOther = new SysUserOther();
        sysUserOther.setLoginType(LoginTypeEnum.weixin.getType());
        sysUserOther.setOpenId(loginVO.getOpenId());
        sysUserOther.setGrantFlag(BoolEnum.TRUE.getType());
        boolean saveUserFlag = true;
        SysUser sysUser = null;
        if (StringUtils.isNotBlank(loginVO.getIdcard())) {
            if (!IdcardUtil.isValidCard(loginVO.getIdcard())){
                throw new AppException("请输入正确的身份证");
            }
            QueryWrapper<SysUser> queryIdcareWrapper = new QueryWrapper<>();
            queryIdcareWrapper.lambda().eq(SysUser::getIdcard,UserSecureUtil.aesEncrypt(loginVO.getIdcard()))
                    .eq(SysUser::getUserType,loginVO.getUserType())
                    .eq(SysUser::getDel,BoolEnum.FALSE.getType());
            checkUserType(queryIdcareWrapper,loginVO);
            List<SysUser> sysUsers = sysUserService.list(queryIdcareWrapper);
            if (!CollectionUtils.isEmpty(sysUsers)) {
                sysUser = sysUsers.get(0);
                sysUserOther.setUserId(sysUser.getUserId());
                saveUserFlag = false;
            }
        }else{
            if (StringUtils.isNotBlank(loginVO.getCellphone())) {
                QueryWrapper<SysUser> queryCellphoneWrapper = new QueryWrapper<>();
                queryCellphoneWrapper.lambda().eq(SysUser::getCellphone, UserSecureUtil.aesEncrypt(loginVO.getCellphone()))
                        .eq(SysUser::getUserType,loginVO.getUserType())
                        .eq(SysUser::getDel,BoolEnum.FALSE.getType());
                checkUserType(queryCellphoneWrapper,loginVO);
                List<SysUser> sysUsers = sysUserService.list(queryCellphoneWrapper);
                if (!CollectionUtils.isEmpty(sysUsers)) {
                    sysUser = sysUsers.get(0);
                    sysUserOther.setUserId(sysUser.getUserId());
                    saveUserFlag = false;
                }
            }
        }
        if (saveUserFlag){
            UserVO userVO = Convert.convert(UserVO.class,loginVO);
            userVO.setNikeName(winxinVO.getNickName());
            userVO.setPhotoPath(winxinVO.getAvatarUrl());
            userIntegration.addUser(userVO);
            sysUser=Convert.convert(SysUser.class,userVO);
            sysUserOther.setUserId(sysUser.getUserId());
        }
        sysUserOtherService.save(sysUserOther);
        if (sysUser==null){
            throw new AppException("生成用户信息失败");
        }

        return getTokenVO(loginVO,sysUser);
    }

    /**
     * 获取第三方登录信息
     * */
    private void getUserOhter(QueryWrapper<SysUser> queryWrapper,LoginVO loginVO){
        List<SysUserOther> list = getOtherList(loginVO.getOpenId(),loginVO.getLoginType());
        if (CollectionUtils.isEmpty(list)){
            if(LoginTypeEnum.weixin.getType().equalsIgnoreCase(loginVO.getLoginType())){
                WinxinVO winxinVO = new WinxinVO();
                winxinVO.setOpenId(loginVO.getOpenId());
                throw new AppException(ErrorEnum.SYSTEM_ERROR_NO_BIND,winxinVO);
            }else if(LoginTypeEnum.alipay.getType().equalsIgnoreCase(loginVO.getLoginType())){
                throw new AppException(ErrorEnum.SYSTEM_ERROR_NO_BIND);
            }else if(LoginTypeEnum.dingding.getType().equalsIgnoreCase(loginVO.getLoginType())){
                throw new AppException(ErrorEnum.SYSTEM_ERROR_NO_BIND);
            }
        }
        List<String> userIdList = list.stream().map(SysUserOther::getUserId).collect(Collectors.toList());
        queryWrapper.lambda().in(SysUser::getUserId,userIdList);
    }
    private List<SysUserOther> getOtherList(String openId,String loginType){
        QueryWrapper<SysUserOther> queryOtherWrapper = new QueryWrapper<>();
        queryOtherWrapper.lambda().select(SysUserOther::getUserId)
                .eq(SysUserOther::getOpenId,openId)
                .eq(SysUserOther::getLoginType,loginType);
        List<SysUserOther> list = sysUserOtherService.list(queryOtherWrapper);
        return list;
    }
    @Override
    @OpApi(funcCode="LOGOUT0001",title = "用户退出",funcType= FuncTypeEnum.other,publicFlag = BoolEnum.TRUE)
    public void logout(String accessToken) {
        tokenLoginHelper.logout(accessToken);
    }

    /**
     * 校验设置的时间范围内最大登入次数
     */
    private void checkLoginMaxCnt(LoginVO loginVO) {
        String loginType = loginVO.getLoginType();
        String loginCntKey = "";
        Integer loginCnt = 1;
        String maxCntKey = "";
        boolean checkImgCode = false;
        if (loginType.equals(LoginTypeEnum.username.getType())) {
            if (StringUtils.isBlank(loginVO.getUserName())) {
                throw new AppException("用户名不能为空！");
            }
            if (StringUtils.isBlank(loginVO.getUserPassword())) {
                throw new AppException("密码不能为空！");
            }
            loginCntKey = SecureUtil.md5(CacheConst.LOGIN_CNT_USER + loginVO.getUserName()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;
            maxCntKey = SecureUtil.md5(CacheConst.LOGIN_USER_CLOCK_MAX_CNT + loginVO.getUserName()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType());
            checkImgCode = true;
        } else if (loginType.equals(LoginTypeEnum.cellphone.getType())) {
            if (StringUtils.isBlank(loginVO.getCellphone())) {
                throw new AppException("手机号码不能为空！");
            }
            if (StringUtils.isBlank(loginVO.getShortMsgCode())) {
                throw new AppException("手机验证码不能为空！");
            }
            this.checkShortCode(loginVO.getCellphone(),loginVO.getShortMsgCode());

            loginCntKey = SecureUtil.md5(CacheConst.LOGIN_CNT_USER + loginVO.getCellphone()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;
            maxCntKey = SecureUtil.md5(CacheConst.LOGIN_USER_CLOCK_MAX_CNT + loginVO.getCellphone()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;
            checkImgCode = true;
        } else if (loginType.equals(LoginTypeEnum.email.getType())) {
            if (StringUtils.isBlank(loginVO.getEmail())) {
                throw new AppException("邮箱不能为空！");
            }
            if (StringUtils.isBlank(loginVO.getEmailCode())) {
                throw new AppException("邮箱验证码不能为空！");
            }
            String emailKey = CacheConst.LOGIN_EMAIL_CODE + loginVO.getEmail();
            if (redisUtil.hasKey(emailKey)){
                String emailCode = (String) redisUtil.get(emailKey);
                if (!emailCode.equalsIgnoreCase(loginVO.getEmailCode())){
                    throw new AppException("邮箱验证码不正确");
                }
            }else{
                throw new AppException("邮箱验证码已过期，请重新发送");
            }

            loginCntKey = SecureUtil.md5(CacheConst.LOGIN_CNT_USER + loginVO.getEmail()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;
            maxCntKey = SecureUtil.md5(CacheConst.LOGIN_USER_CLOCK_MAX_CNT + loginVO.getEmail()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;
            checkImgCode = true;
        } else {
            if (StringUtils.isBlank(loginVO.getOpenId())) {
                throw new AppException("第三方登录Id不能为空！");
            }
            loginCntKey = SecureUtil.md5(CacheConst.LOGIN_CNT_USER + loginVO.getOpenId()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;
            maxCntKey = SecureUtil.md5(CacheConst.LOGIN_USER_CLOCK_MAX_CNT + loginVO.getOpenId()+":"+loginVO.getUserType()+":"+loginVO.getLoginType()+":"+loginVO.getEquipmentType()) ;

        }
        if (StringUtils.isNotBlank(maxCntKey)) {
            if (redisUtil.hasKey(maxCntKey)) {
                throw new AppException("用户因10分钟内登入次数过多，被锁定1小时");
            }
        }
        if (StringUtils.isNotBlank(loginCntKey)) {
            if (loginMax==null){
                loginMax = 10;
            }
            if (clockTime==null){
                clockTime = 3600L;
            }
            if (loginImgCodeMax==null){
                loginImgCodeMax = 5;
            }
            if (redisUtil.hasKey(loginCntKey)) {
                loginCnt = (Integer) redisUtil.get(loginCntKey) + 1;
                if (loginCnt > loginMax) {
                    if (StringUtils.isNotBlank(maxCntKey)) {
                        redisUtil.set(maxCntKey, loginCnt, clockTime);
                    }

                }
                if (checkImgCode) {
                    if (loginCnt > loginImgCodeMax) {
                        if (StringUtils.isBlank(loginVO.getImgCode())) {
                            throw new AppException(ErrorEnum.SYSTEM_ERROR_SHOW_IMG_CODE);
                        }
                    }
                    if (StringUtils.isNotBlank(loginVO.getImgCode())) {
                        if (StringUtils.isBlank(loginVO.getLoginKey())) {
                            throw new AppException("登入唯一key不能为空");
                        }
                        String imgKey = CacheConst.LOGIN_IMG_CODE + loginVO.getLoginKey();
                        if (redisUtil.hasKey(imgKey)) {
                            String imgCode = (String) redisUtil.get(imgKey);
                            if (!imgCode.equalsIgnoreCase(loginVO.getImgCode())) {
                                throw new AppException("图片验证码不正确");
                            }
                        } else {
                            throw new AppException("图片验证码已过期，请重新刷新");
                        }
                    }
                }
                Long time = redisUtil.getExpire(loginCntKey);
                Date date = new Date(Instant.now().toEpochMilli() + time * 1000);
                redisUtil.set(loginCntKey,loginCnt,checkTime);
                redisUtil.expireAt(loginCntKey,date);
            } else {
                redisUtil.set(loginCntKey, loginCnt, checkTime);
            }
        }
    }
    /**
     * 校验手机验证码
     * */
    private void checkShortCode(String cellphone,String shortMsgCode){
        String cellphoneKey = CacheConst.LOGIN_SHORT_MSG_CODE + cellphone;
        if (redisUtil.hasKey(cellphoneKey)){
            String shortCode = (String) redisUtil.get(cellphoneKey);
            if (!shortCode.equalsIgnoreCase(shortMsgCode)){
                throw new AppException("手机验证码不正确");
            }
        }else{
            throw new AppException("手机验证码已过期，请重新发送");
        }
    }
    /**
     * 校验登入用户信息
     */
    private void checkLogin(SysUser sysUser, LoginVO loginVO) {
        if (sysUser==null) {
            String msg= "用户信息不存在，请先注册";
            if (UserTypeEnum.COMPANY.getType().equalsIgnoreCase(loginVO.getUserType())){
                msg="该企业账号不存在，请使用正确的统一社会信用代码/专管员/法人账号登录";
            }
            if (LoginTypeEnum.weixin.getType().equalsIgnoreCase(loginVO.getLoginType())){
                throw new AppException(ErrorEnum.SYSTEM_ERROR_NO_BIND);
            }
            if (LoginTypeEnum.alipay.getType().equalsIgnoreCase(loginVO.getLoginType())){
                throw new AppException(ErrorEnum.SYSTEM_ERROR_NO_BIND);
            }
            if (LoginTypeEnum.dingding.getType().equalsIgnoreCase(loginVO.getLoginType())){
                throw new AppException(ErrorEnum.SYSTEM_ERROR_NO_BIND);
            }
            throw new AppException(msg);
        }
        if (sysUser.getStatus().equals(BoolEnum.FALSE.getType())) {
            throw new AppException("用户被锁定");
        }
        //校验数据是否异常
        String hashCode = UserSecureUtil.enSysUser(sysUser);
        if (!hashCode.equals(sysUser.getHashcode())) {
            throw new AppException("用户数据异常");
        }
        String loginType = loginVO.getLoginType();
        if (loginType.equals(LoginTypeEnum.username.getType())) {
            if (StringUtils.isBlank(loginVO.getUserPassword())) {
                throw new AppException("密码不能为空");
            }
            // 密码校验
            String userPassword = UserSecureUtil.createPassword(sysUser.getUserId(),loginVO.getUserPassword());
            //密码不为空，按密码校验
            if (!sysUser.getUserPassword().equals(userPassword)) {
                throw new AppException("密码有误");
            }
        }

    }

    private void checkUserType(QueryWrapper<SysUser> queryWrapper,LoginVO loginVO){
        if (UserTypeEnum.COMPANY.getType().equalsIgnoreCase(loginVO.getUserType())){
            if (StringUtils.isBlank(loginVO.getOrgId())){
                throw new AppException("请选择需要登录的企业或单位");
            }
            queryWrapper.lambda().eq(SysUser::getOrgId, loginVO.getOrgId());

        }else if (UserTypeEnum.CLIENT.getType().equalsIgnoreCase(loginVO.getUserType())){
            if (StringUtils.isBlank(loginVO.getClientId())){
                throw new AppException("请选择需要登录的应用系统");
            }
            queryWrapper.lambda().eq(SysUser::getClientId, loginVO.getClientId());
        }
    }
    /**
     * 生成用户登录信息
     * */
    private SessionInfo createSessionInfo(SysUser sysUser,LoginVO loginVO){
        SessionInfo sessionInfo = Convert.convert(SessionInfo.class, sysUser);
        SysUserBasic sysUserBasic = sysUserBasicService.getById(sysUser.getUserId());
        if (sysUserBasic != null) {
            BeanUtils.copyProperties(sysUserBasic, sessionInfo);
        }
        sessionInfo.setLoginKey(loginVO.getLoginKey());
        sessionInfo.setLoginType(loginVO.getLoginType());
        sessionInfo.setEquipmentId(loginVO.getEquipmentId());
        sessionInfo.setEquipmentType(loginVO.getEquipmentType());
        sessionInfo.setOpenId(loginVO.getOpenId());
        sessionInfo.setSystemCode(loginVO.getSystemCode());
        sessionInfo.setSystemName(loginVO.getSystemName());
        sessionInfo.setOrgId(loginVO.getOrgId());
        sessionInfo.setClientId(loginVO.getClientId());
        if (StringUtils.isNotBlank(loginVO.getLoginType())) {
            sessionInfo.setLoginTypeName(LoginTypeEnum.getByType(loginVO.getLoginType()).getName());
        }
        sessionInfo.setVersion(loginVO.getVersion());
        sessionInfo.setCheckPrivilege(true);
        if (StringUtils.isBlank(sysUser.getUserType())) {
            sessionInfo.setUserType(UserTypeEnum.USER.getType());
        }
        sessionInfo.setUserTypeName(UserTypeEnum.getByType(sessionInfo.getUserType()).getName());
        sessionInfo.setIdcard(UserSecureUtil.aesDecrypt(sessionInfo.getIdcard()));
        sessionInfo.setCellphone(UserSecureUtil.aesDecrypt(sessionInfo.getCellphone()));
        sessionInfo.setEmail(UserSecureUtil.aesDecrypt(sessionInfo.getEmail()));
        if (EquipmentTypeEnum.APP.getType().equalsIgnoreCase(loginVO.getEquipmentType())){
            // app不校验接口权限
            sessionInfo.setCheckPrivilege(false);
        } else{
            // 获取用户系统级权限
            sessionInfo.setSystemPrivileges(getUserPrivilegeObjectIds(sysUser.getUserId(), ObjectTypeEnum.system.getType()));
            // 获取角色权限
            sessionInfo.setRoles(getUserPrivilegeObjectIds(sysUser.getUserId(), ObjectTypeEnum.role.getType()));
            // 获取路由功能
            List<SysRouter> sysRouterList =sysRouterService.selectByUserid(sysUser.getUserId());
            Map<String, Set<String>> map = new HashMap<>();
            if (!CollectionUtils.isEmpty(sysRouterList)) {
                List<SysRouterFuncResult> routerFuncResults = sysRouterFuncService.selectApiByRouter(sysUser.getUserId(),null);
                Map<String, List<SysRouterFuncResult>> groupBy = new HashMap<>();
                if (!CollectionUtils.isEmpty(routerFuncResults)) {
                    groupBy = routerFuncResults.stream().collect(Collectors.groupingBy(SysRouterFuncResult::getRouterId));
                }
                for (SysRouter sysRouter : sysRouterList) {
                    Set<String> apis = new HashSet<>();
                    List<SysRouterFuncResult> resultList = groupBy.get(sysRouter.getRouterId());
                    if (!CollectionUtils.isEmpty(resultList)) {
                        apis = resultList.stream().map(SysRouterFuncResult::getFuncCode).collect(Collectors.toSet());
                    }
                    map.put(sysRouter.getRouterId(), apis);
                }
            }
            sessionInfo.setRouters(map);
            // 获取用户接口权限
            List<String> funcList =sysFunctionService.selectApiByUserId(sysUser.getUserId());
            sessionInfo.setApiList(CollectionUtils.isEmpty(funcList)?null:new HashSet<>(funcList));
            // 获取组织权限
            List<String> orglist = sysUserPrivilegeService.selectOrgPriByUserId(sysUser.getUserId());
            sessionInfo.setOrgIds(CollectionUtils.isEmpty(orglist)?null:new HashSet<>(orglist));
        }

        return sessionInfo;
    }

    /**
     * 根据条件获取权限id 公共方法
     **/
    private Set<String> getUserPrivilegeObjectIds(String userId,String objectType) {
        QueryWrapper<SysUserPrivilege> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysUserPrivilege::getDel,BoolEnum.FALSE.getType())
                .eq(SysUserPrivilege::getUserId,userId).eq(SysUserPrivilege::getObjectType,objectType);
        List<SysUserPrivilege> list = sysUserPrivilegeService.list(queryWrapper);
        Set<String> set = new HashSet<>();
        if (!CollectionUtils.isEmpty(list)) {
            set = list.stream().map(SysUserPrivilege::getObjectId).collect(Collectors.toSet());
        }
        return set;
    }
    /**
     * 获取用户登录信息token
     * */
    private TokenVO getTokenVO(LoginVO loginVO,SysUser sysUser){
        LoginLogVO loginLogVO = Convert.convert(LoginLogVO.class,loginVO);
        loginLogVO.setLoginFlag(BoolEnum.TRUE.getType());
        loginLogVO.setLoginTime(new Date());
        loginLogVO.setUserId(sysUser.getUserId());
        loginLogVO.setUserName(sysUser.getUserName());
        SessionInfo sessionInfo = createSessionInfo(sysUser, loginVO);
        TokenVO tokenVO = tokenLoginHelper.login(sessionInfo);
        loginLogVO.setAccessToken(tokenVO.getAccessToken());
        loginLogVO.setLoginFlag(BoolEnum.TRUE.getType());
        loginLogVO.setOnlineFlag(BoolEnum.TRUE.getType());
        loginLogIntegration.saveLogin(loginLogVO);
        return tokenVO;
    }
}
